package core.base;

import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Pattern;

import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest;

import core.Pilot;
import core.helpers.LoggerHelper;

/**
 * The base class for test classes.
 */
public abstract class TestBase
{
	protected static Pilot pilot;
	// Test suite data
	public static String TEST_SUITE_NAME;
	public static String TEST_SUITE_DATE;
	public static String TEST_SUITE_TIME;
	// Test sphase data
	public static String TEST_PHASE_NAME;
	public static String TEST_PHASE_TIME;

	public TestBase()
	{
		pilot = new Pilot();
		TEST_SUITE_NAME = getCallerName(getCallerPath(3));
		System.setProperty("testSuiteName", TEST_SUITE_NAME);
	}

	/**
	 * Actions before all tests
	 * @param p_os
	 *            Test OS name
	 * @param p_platform
	 *            Test platform name
	 * @param p_site
	 *            Test site name
	 * @param p_browserName
	 *            Test browser name
	 */
	@BeforeTest
	public void testSuiteInit()
	{
		// Set test suite date start
		TEST_SUITE_DATE = getCurrentDate("yyyy-MM-dd");
		System.setProperty("testSuiteDate", TEST_SUITE_DATE);
		// Set test suite time start
		TEST_SUITE_TIME = getCurrentDate("HH-mm-ss");
		System.setProperty("testSuiteTime", TEST_SUITE_TIME);
		// Set test phase name
		TEST_PHASE_NAME = getMethodName();
		// Set test phase start time
		TEST_PHASE_TIME = getCurrentTime("HH-mm-ss");
		// Set test screenshot path
		Pilot.TEST_SCREENSHOT_FILENAME = TEST_PHASE_NAME + "_" + TEST_SUITE_DATE + "_" + TEST_PHASE_TIME + ".png";
		Pilot.TEST_SCREENSHOT_PATH = System.getProperty("user.dir")
				+ "\\reports"
				+ "\\" + TEST_SUITE_NAME
				+ "\\" + TEST_SUITE_DATE
				+ "\\" + TEST_SUITE_TIME
				+ "\\" + Pilot.TEST_SCREENSHOT_FILENAME;

		printTestStart("START TEST SUITE [" + TEST_SUITE_NAME + "]");

		try
		{
			/*
			 * manager..db().connect(
			 * manager.config().DB_HOST,
			 * manager.config().DB_PORT,
			 * manager.config().DB_NAME,
			 * manager.config().DB_USER,
			 * manager.config().DB_PASSWORD);
			 * manager.db().isConnected();
			 */
		}
		catch (Exception p_ex)
		{
			Assert.assertTrue(false, log().getErrorsAndWarnings());
		}

		try
		{
			pilot.init(pilot.dashboard().getOS(), pilot.dashboard().getPlatform(), pilot.dashboard().getSiteUrl(), pilot.dashboard().getBrowserName());

		}
		catch (Exception p_ex)
		{
			Assert.assertTrue(false, log().getErrorsAndWarnings());
		}

	}

	/**
	 * Actions before every test method
	 */
	@BeforeMethod
	public void testInit(Method p_method)
	{
		// Set test phase name
		TEST_PHASE_NAME = p_method.getName();
		System.setProperty("phaseName", TEST_PHASE_NAME);
		// Set test phase start time
		TEST_PHASE_TIME = pilot.date().getCurrentTime("HH-mm-ss");
		System.setProperty("testTime", TEST_PHASE_TIME);
		// Set path to screenshots
		Pilot.TEST_SCREENSHOT_FILENAME = TEST_PHASE_NAME + "_" + TEST_SUITE_DATE + "_" + TEST_PHASE_TIME + ".png";
		Pilot.TEST_SCREENSHOT_PATH = System.getProperty("user.dir")
				+ "\\reports"
				+ "\\" + TEST_SUITE_NAME
				+ "\\" + TEST_SUITE_DATE
				+ "\\" + TEST_SUITE_TIME
				+ "\\" + Pilot.TEST_SCREENSHOT_FILENAME;

		printTestStart("START TEST [" + TEST_PHASE_NAME + "]");

		pilot.dashboard().setTestName(p_method.getName());
		pilot.dashboard().setStatus(2);
		pilot.dashboard().setDateStart(pilot.date().getCurrentDate("yyyy-MM-dd HH:mm:ss"));
		pilot.dashboard().setTimeStart(pilot.date().getCurrentTimeInMilliseconds());
		pilot.dashboard().setTimeRun(0);

		// db().addTestData(testModel());
	}

	/**
	 * Actions after every test method
	 */
	@AfterMethod
	public void testQuit()
	{
		printTestEnd("END TEST [" + TEST_PHASE_NAME + "]");

		pilot.dashboard().setTimeEnd(pilot.date().getCurrentTimeInMilliseconds());
		pilot.dashboard().setDateEnd(pilot.date().getCurrentDate("yyyy-MM-dd HH:mm:ss"));
		pilot.dashboard().setTimeRun(pilot.dashboard().getTimeEnd() - pilot.dashboard().getTimeStart());
		// db().updateTestData(testModel());

		log().clear();
	}

	/**
	 * Actions after all tests
	 */
	@AfterTest
	public void testSuiteQuit()
	{
		// if (manager.testModel().getApplicationType().equals("selenium"))
		// {
		if (pilot.config().SCREENLOGGER_ENABLED)
		{
			// pilot.screenLogger().stop();
		}
		// lead.db().disconnect();
		pilot.driver().stop();
		// }
		printTestEnd("END TEST SUITE [" + TEST_SUITE_NAME + "]");
	}

	/**
	 * Gets current method name
	 * @return Method name
	 */
	private String getMethodName()
	{
		StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
		StackTraceElement stackTraceElement = stacktrace[2];// coz 0th will be getStackTrace so 1st
		String methodName = stackTraceElement.getMethodName();
		return methodName;
	}

	/**
	 * Prints test start info
	 * @param p_message
	 *            Text message
	 */
	private void printTestStart(String p_message)
	{
		System.out.println("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> " + p_message + " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
		log().info(p_message);
	}

	/**
	 * Prints test end info
	 * @param p_message
	 *            Text message
	 */
	private void printTestEnd(String p_message)
	{
		log().info(p_message);
		System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< " + p_message + " <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
	}

	/**
	 * Gets current date
	 * @param p_format
	 *            Date format
	 * @return Date
	 */
	private String getCurrentDate(String p_format)
	{
		Date date = new Date();
		DateFormat dateFormat = new SimpleDateFormat(p_format);
		dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+3"));
		String currentDate = dateFormat.format(date);
		return currentDate;
	}

	/**
	 * Gets the caller name
	 * @param p_callerPath
	 * @return Name of caller class
	 */
	public String getCallerName(String p_callerPath)
	{
		String[] callerPathSplit = p_callerPath.split(Pattern.quote("."));
		String callerName = callerPathSplit[callerPathSplit.length - 1];

		return callerName;
	}

	/**
	 * Gets the caller name
	 * @param p_callerPath
	 * @return Name of caller class
	 */
	public String getCallerPath(int p_depth)
	{
		String callerPath = Thread.currentThread().getStackTrace()[p_depth].getClassName();

		return callerPath;
	}

	/**
	 * Link method to LoggerHelper
	 * @return LoggerHelper istance
	 */
	public LoggerHelper log()
	{
		return pilot.log();
	}

	public String getCurrentTime(String p_timeFormat)
	{
		Date date = new Date();
		DateFormat df = new SimpleDateFormat("HH:mm:ss yyyy/MM/dd");
		DateFormat time = new SimpleDateFormat(p_timeFormat);
		df.setTimeZone(TimeZone.getTimeZone("Europe/Kiev"));
		String currentTime = time.format(date);

		return currentTime;
	}
}
